﻿using Bussiness.DEV;
using Common;
using Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;

namespace Bussiness
{
    public class BLL
    {
        private List<Device> _DeviceList=new List<Device>();
        public UI _UI = new UI();
        public DAL _DAL = new DAL();
        private SYN _SYN;
        public List<ScadaData> _ScadaDataList = new List<ScadaData>();
        private Config _Config;
        
        /// <summary>
        /// 启动采集
        /// </summary>
        public void Start()
        {
            Task.Factory.StartNew(()=>{
                _Config = _DAL.GetConfig();
                LOG._LogDir = _Config.LogPath;
                _DeviceList = _DAL.GetDeviceList();
                _SYN = new SYN(_Config.WebsocketURL, _UI);
                _SYN.ConnectServer();
                _UI.StartShowMessage();
                InitScadaData();
                DevPolling();
                SendScadaData();
            });
        }

        /// <summary>
        /// 初始化采集数据列表
        /// </summary>
        public void InitScadaData()
        {
            foreach (var dev in _DeviceList)
            {
                ScadaData scadaData = new ScadaData();
                scadaData.DevCode = dev.DevCode;
                scadaData.DevName = dev.DevName;
                scadaData.DevType = dev.DevTypeCode;
                scadaData.DataList = new List<Cfg_Field>();
                _ScadaDataList.Add(scadaData);
            }
        }

        /// <summary>
        /// 发送采集数据
        /// </summary>
        public void SendScadaData()
        {
            List<DeviceType> deviceTypeList = _DAL.GetDeviceTypeList();
            foreach(var devType in deviceTypeList)
            {
                Task.Factory.StartNew(() =>
                {
                    while (true)
                    {
                        lock (_ScadaDataList)
                        {
                            List<ScadaData> scadaDataList = _ScadaDataList.Where(p =>!string.IsNullOrEmpty(p.DevType) 
                            && p.DevType.Equals(devType.DeviceTypeCode) 
                            && p.DataList.Count>0 
                            && !p.HasUp).ToList();
                            lock (_SYN)
                            {
                                if (scadaDataList.Count > 0)
                                {
                                    int pageCount = scadaDataList.Count / 5;
                                    if (_ScadaDataList.Count % 5 > 0)
                                    {
                                        pageCount++;
                                    }

                                    //分页发送，服务端可能有接收缓存大小限制
                                    for (var pageIndex = 0; pageIndex < pageCount; pageIndex++)
                                    {
                                        List<ScadaData> _scadaDataList = scadaDataList.Skip(pageIndex * 5).Take(5).ToList();
                                        _SYN.SendScadaData(_scadaDataList);
                                        Thread.Sleep(1000);
                                    }
                                }
                            }
                        }
                        
                        Thread.Sleep(devType.CaptureFreq.Value*1000);
                    }
                });
            }
        }

        public void DevPolling()
        {
            List<DeviceType> deviceTypeList = _DAL.GetDeviceTypeList();
            foreach(var deviceType in deviceTypeList)
            {
                DeviceType _deviceType = deviceType;

                try
                {
                    Assembly assembly = Assembly.GetExecutingAssembly();
                    IDEV idev = (IDEV)assembly.CreateInstance("Bussiness." + _deviceType.DeviceTypeCode);
                    if (idev == null)
                    {
                        _UI._DeviceMessageQueue.Enqueue(new DeviceMessage()
                        {
                            Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                            Title = _deviceType.DeviceTypeName + "设备连接",
                            Content = "未找到设备类型【" + _deviceType.DeviceTypeName + "】对应的驱动类【" + _deviceType.DeviceTypeCode + "】"
                        });
                        continue;
                    }

                    List<Device> deviceList = _DeviceList.Where(p => !string.IsNullOrEmpty(p.DevTypeCode) && p.DevTypeCode.Equals(_deviceType.DeviceTypeCode)).ToList();
                    foreach (var device in deviceList)
                    {
                        Device _device = device;
                        List<DevicePOI> devicePOIList = _DAL.GetDevicePOIList(_device.DevTypeGuid);

                        idev.Device = device;
                        idev.DevicePOIList = devicePOIList;

                        Task.Factory.StartNew(() =>
                        {
                            while (true)
                            {
                                try
                                {
                                    bool issuccess = false;
                                    var result = idev.Connect();
                                    _UI._DeviceMessageQueue.Enqueue(new DeviceMessage()
                                    {
                                        Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                                        Title = _deviceType.DeviceTypeName + "设备连接",
                                        Content = "连接【" + _device.DevName + "】【" + _device.IP + ":" + _device.Port + "】" + (result.Success ? "成功" : ("失败" + result.Msg))
                                    });

                                    _device.State = result.Success ? 1 : 0;
                                    _UI.UpdateDeviceState(_device);
                                    issuccess = result.Success;
                                    if (!issuccess)
                                    {
                                        Thread.Sleep(3000);
                                        continue;
                                    }

                                    while (true)
                                    {
                                        if (!issuccess)
                                        {
                                            _UI._DeviceMessageQueue.Enqueue(new DeviceMessage()
                                            {
                                                Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                                                Title = _deviceType.DeviceTypeName + "设备连接",
                                                Content = _device.DevName + "重连"
                                            });

                                            break;
                                        }

                                        var readResult = idev.Read();
                                        issuccess = readResult.Success;
                                        if (readResult.Success)
                                        {
                                            lock (_ScadaDataList)
                                            {
                                                int index = _ScadaDataList.FindIndex(p => p.DevCode.Equals(_device.DevCode));
                                                if (index > -1)
                                                {
                                                    _ScadaDataList[index].HasUp = false;
                                                    _ScadaDataList[index].DataList = readResult.Data;
                                                }
                                            }
                                        }

                                        Thread.Sleep(3000);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    _UI._DeviceMessageQueue.Enqueue(new DeviceMessage()
                                    {
                                        Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                                        Title = _deviceType.DeviceTypeName + "数采业务异常",
                                        Content = ex.ToString() + ex.StackTrace
                                    });

                                    Thread.Sleep(60000);
                                }
                            }
                        });
                    }
                }
                catch(Exception ex)
                {
                    _UI._DeviceMessageQueue.Enqueue(new DeviceMessage()
                    {
                        Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                        Title = _deviceType.DeviceTypeName + "数采业务异常",
                        Content = ex.ToString() + ex.StackTrace
                    });
                }
            }
        }
    }
}
